# coding: utf-8

# -------------------------------------------------------------------------------
# Name:         testcase_task.py
# Description:  批量执行测试用例
# Author:       XiangjunZhao
# EMAIL:        2419352654@qq.com
# Date:         2019/11/27 15:29
# -------------------------------------------------------------------------------
import json
import threading
from celery import shared_task

from apps.BasicAuthService.models import User
from apps.CeleryScheduledTaskService.HttpAutoTestService.utils import send_testreport
from apps.HttpAutoTestService.core.http_client import HttpSession
from apps.HttpAutoTestService.core.http_session_context import HttpSessionContext
from apps.HttpAutoTestService.core.http_testcase_runner import HttpTestcaseRunner
from apps.HttpAutoTestService.models import Testcase, TestcaseResult
from utils.common import get_version


def exec_testcase(testcases=None, executor=None, is_periodictask=True, version=None):
    '''
    执行测试用例
    :param executor: 当前执行(登录)用户
    :param testcases: 被执行的用例集合
    :param is_periodictask:标记是否是定时任务
    :param version: 版本号
    :return:
    '''
    testcase_result_list = []
    testcase_list = []
    for testcase in testcases:
        # 1、获取用例所属接口
        api = testcase.api
        # 2、获取接口的运行环境
        environment = api.environment
        # 3、获取接口所属项目
        project = api.project
        if environment:
            # 4、获取接口运行环境全局参数
            environment_variables = json.loads(environment.global_variables)
        else:
            # 5、获取项目默认运行环境
            environment = project.default_environment
            # 6、获取项目默认运行环境全局参数
            environment_variables = json.loads(environment.global_variables)
        # 6、获取项目的全局参数
        project_variables = json.loads(project.global_variables)
        # 7、创建HttpSession实例
        http_session = HttpSession()
        # 8、创建HttpSessionContext实例
        http_session_context = HttpSessionContext(environment_variables=environment_variables,
                                                  project_variables=project_variables)
        # 9、创建HttpTestcaseRunner实例
        http_testcase_runner = HttpTestcaseRunner(http_session=http_session, http_session_context=http_session_context,
                                                  environment=environment, project=project, api=api, testcase=testcase)
        temp_testcase_result_list = http_testcase_runner.run(executor=executor, is_periodictask=is_periodictask)
        for temp_testcase_result in temp_testcase_result_list:
            temp_testcase_result.version = version
            testcase_result_list.append(temp_testcase_result)
            if temp_testcase_result:
                testcase.status = temp_testcase_result.status
                testcase_list.append(testcase)
    TestcaseResult.objects.bulk_create(testcase_result_list)
    Testcase.objects.bulk_update(testcase_list, fields=['status'])


@shared_task
def batch_exec_testcase(testcases=None, executor_id=None, is_periodictask=True, version=None):
    '''
    批量执行测试用例
    :param executor_id: 当前执行(登录)用户id
    :param testcases: 被执行的用例id集合
    :param is_periodictask:标记是否是定时任务
    :param version: 版本号
    :return:
    '''
    # 获取执行者
    executor = User.objects.get(id=executor_id)

    if not version:
        # 执行定时任务时，参数version为None，此需要设置version；当批量执行时，参数version为传入值
        version = get_version()
    # 执行定时任务时，参数testcases类型为字符串，需要转换成列表；当批量执行时，参数testcases类型为列表
    if isinstance(testcases, str):
        testcases = eval(testcases) if isinstance(eval(testcases), list) else []
    testcase_list = Testcase.objects.filter(id__in=testcases, is_deleted=False)

    # 启动线程数量
    threads_num = 5
    quotient, remainder = divmod(len(testcase_list), threads_num)

    testcases_temp = [[] for i in range(threads_num)]
    for i in range(threads_num):
        testcases_temp[i] = testcase_list[i * quotient:(i + 1) * quotient]

    for i in range(remainder):
        testcases_temp[i].append(testcase_list[threads_num * quotient + i])

    threads = []
    for i in range(threads_num):
        t = threading.Thread(target=exec_testcase, args=(testcases_temp[i], executor, is_periodictask, version))
        threads.append(t)

    for t in threads:
        t.start()

    for t in threads:
        t.join()

    # 此处可以增加发送测试报告
    send_testreport(report_type='testcase', version=version)

    return f"批量执行用例已完成【用户ID：{executor_id}，用例ID：{testcases}，是否是定时任务：{is_periodictask}，版本号：{version}】"
